package com.haidung.photojourney.utils;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

import android.location.Location;
import android.media.ExifInterface;

public final class LocationUtil {
    // The update interval
    public static final int UPDATE_INTERVAL = 10 * 1000;
    // A fast interval ceiling
    public static final int FAST_INTERVAL_CEILING = 1 * 1000;
    // For checking a valid location
    public static final long FIX_RECENT_BUFFER_TIME = 60 * 1000;

    public static final String GPS_NORTH = "N";
    public static final String GPS_SOUTH = "S";
    public static final String GPS_EAST = "E";
    public static final String GPS_WEST = "W";

    public static final String GPS_DATE_STAMP = "yyyy:MM:dd";
    public static final String GPS_TIME_STAMP = "HH:mm:ss";
    public static final String GMT_TIME_ZONE = "HH:mm:ss";

    public static boolean isLocationValid(Location location) {
        return location != null && (location.getTime() >= (System.currentTimeMillis() - FIX_RECENT_BUFFER_TIME));
    }

    public static void geoTagged(Location location, ExifInterface exif) throws IOException {
        String latitude = LocationUtil.convertDecimalToDMS(location.getLatitude());
        String latitudeRef = location.getLatitude() >= 0 ? GPS_NORTH : GPS_SOUTH;
        String longtitude = convertDecimalToDMS(location.getLongitude());
        String longtitudeRef = location.getLongitude() >= 0 ? GPS_EAST : GPS_WEST;
        ;
        String altitude = (int) (location.getAltitude() * 1000) + "/1000";
        String altitudeRef = location.getAltitude() >= 0 ? "0" : "1";

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(location.getTime());
        DateFormat dateFormat = new SimpleDateFormat(GPS_DATE_STAMP, Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone(GMT_TIME_ZONE));
        DateFormat timeFormat = new SimpleDateFormat(GPS_TIME_STAMP, Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone(GMT_TIME_ZONE));
        String dateStamp = dateFormat.format(calendar.getTime());
        String timeStamp = timeFormat.format(calendar.getTime());

        exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, latitude);
        exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, latitudeRef);
        exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, longtitude);
        exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, longtitudeRef);
        exif.setAttribute(ExifInterface.TAG_GPS_ALTITUDE, altitude);
        exif.setAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF, altitudeRef);
        exif.setAttribute(ExifInterface.TAG_GPS_DATESTAMP, dateStamp);
        exif.setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, timeStamp);
        exif.saveAttributes();
    }

    public static String convertDecimalToDMS(double coord) {
        String output, degrees, minutes, seconds;

        // gets the modulus the coordinate divided by one (MOD1). 
        // in other words gets all the numbers after the decimal point.
        // e.g. mod = 87.728056 % 1 == 0.728056
        //
        // next get the integer part of the coord. On other words the whole number part.
        // e.g. intPart = 87

        double mod = coord % 1;
        int intPart = (int) coord;

        // set degrees to the value of intPart
        // e.g. degrees = "87"

        degrees = String.valueOf(intPart);

        // next times the MOD1 of degrees by 60 so we can find the integer part for minutes.
        // get the MOD1 of the new coord to find the numbers after the decimal point.
        // e.g. coord = 0.728056 * 60 == 43.68336
        // mod = 43.68336 % 1 == 0.68336
        //
        // next get the value of the integer part of the coord.
        // e.g. intPart = 43

        coord = mod * 60;
        mod = coord % 1;
        intPart = (int) coord;
        if (intPart < 0) {
            // Convert number to positive if it's negative.
            intPart *= -1;
        }

        // set minutes to the value of intPart.
        // e.g. minutes = "43"
        minutes = String.valueOf(intPart);

        // do the same again for minutes
        // e.g. coord = 0.68336 * 60 == 41.0016
        // e.g. intPart = 41
        coord = mod * 60;
        intPart = (int) (coord * 10000);
        if (intPart < 0) {
            // Convert number to positive if it's negative.
            intPart *= -1;
        }

        // set seconds to the value of intPart.
        // e.g. seconds = "41"
        seconds = String.valueOf(intPart);

        // I used this format for android but you can change it
        // to return in whatever format you like
        // e.g. output = "87/1,43/1,41/1"
        output = degrees + "/1," + minutes + "/1," + seconds + "/10000";

        // Standard output of D°M′S″
        // output = degrees + "°" + minutes + "'" + seconds + "\"";
        return output;
    }
}
